#copyright 2009 Kevin Daley
#This file is a part of Nyst.
#Nyst is free software: you can redistribute it and/or modify
 #   it under the terms of the GNU Lesser General Public License as published by
  #  the Free Software Foundation, either version 3 of the License, or
   # (at your option) any later version.

   # This program is distributed in the hope that it will be useful,
   # but WITHOUT ANY WARRANTY; without even the implied warranty of
   # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   # GNU Lesser General Public License for more details.

   # You should have received a copy of the GNU Lesser General Public License
   # along with this program.  If not, see <http://www.gnu.org/licenses/>.

#Kevin Daley, Lead Developer.  still.horse@gmail.com.

from cerebra import *
import scipy, numpy
import scipy.interpolate 
import string, glob
from numpy.fft import fft
from cmath import *

class node(cerebra.network):
	charset=[[["="]],[["[","]"],["{", "}"]],[["(",")"],["'","'"],[">"],["<"],["-"]],[["\\"],["#"],["%"],["."]],[["v"]]]
	objs=[[],[],[],[],[]]
	def __init__(self,ID, (parents={}, children={}, offset, neighbors={}), (estring, cstrings, sstrings), (resolution, spectrum, number, cell_width, frame_width, mass)):
		network.__init__(network, resolution, spectrum, number, cell_width, frame_width, mass)
		self.ID=ID
		self.vtable={}
		self.parents=parents
		self.children=children
		self.neighbors
		self.offset=offset
		self.estring=string
		self.cstrings=cstrings
		self.sstrings=sstrings
		for i in xrange(self.res_x):
			for j in xrange(self.res_x):
				self.W=1/sqrt(res_x)*numpy.matrix([[exp(2*pi*i*j*(0+1.0j)/(res_x)) for j in xrange(res_x)] for i in xrange(res_x)])
				self.Wi=numpy.invert(W)
	def sub_evolve(self):
		for k in children.keys():
			i=children[i]
			i.sub_evolve()
			for a in xrange(self.spectrum):
				if(i.sstrings[a] in self.sstrings):
					x = scipy.linspace(i.offset[0],i.offset[0]+i.res_x*i.cellwidth, i.cellwidth)
					y = scipy.linspace(i.offset[0],i.offset[0]+i.res_y*i.cellwidth, i.cellwidth)
					z = i.number[a]
					spl = scipy.interpolate.RectBivariateSpline(x,y,z) 
					nx=scipy.linspace(i.offset[0],i.offset[0]+i.res_x*i.cellwidth, self.cellwidth)
					ny=scipy.linspace(i.offset[0],i.offset[0]+i.res_y*i.cellwidth, self.cellwidth)
					self.number[a]+=spl(nx,ny)
					self.network+=a*self.number[a]*self.mass*exp((0+1.0j)
					self.lambda1[a]+=i.lambda1[a]*(i.res_x*i.res_y*i.cellwidth**2)/(self.res_x*self.res_y*self.cellwidth**2)
					self.lambda2[a]+=i.lambda2[a]*(i.res_x*i.res_y*i.cellwidth**2)/(self.res_x*self.res_y*self.cellwidth**2)
					counter++
			
	def append_child(self,child, string):
		self.children[int(abs(child.ID-self.ID))]=child
		self.cstrings[int(abs(child.ID-self.ID))]=string
		child.parents[int(abs(child.ID-self.ID))]=parent
	def attach_to_parent(self, parent):
		parent.append_child(self, self.estring)
	def change_string(self,string_new):
		self.cstring=string_new
		for i in self.parents
			i.cstrings[int(abs(i.ID-self.ID))]=string_new
	
	def parsestr(self, astring, ix=0):
		punctuation=[]
		digits = "0123456789*"
		number = Word( digits )
		for i in charset[len(self.charset)-(ix+1)]:
			switch(len(i))
				case 1:
					punctuation.append(Optional(i[0])+number)
				case 2:
					punctuation.append(Optional(i[0])+ number+ Optional(i[1]))
		
		grammar=And( punctuation )
		self.objs[ix].append(data)=grammar.scanString(astring)
		astring.replace(data,"*")
		self.parsestr(astring, ix+1)
	def op(self,x,opstr):
		switch opstr:
			case "%":
				return self.W*x
			case "#":
				return self.Wi*x
			case ".":
				return sum(numpy.array([self.number[k,int(u.real/self.cellwidth), int(u.imag/self.cellwidth)] for u in x] ) for k in xrange(self.number.shape[0]), axis=0)
			case "\\"
				return numpy.array([[x(j,k,self.counter) for j in xrange(self.res_x)]]).flatten()
	def op2(self, x, y, opstr):
		switch opstr:
			case "-":
				b=numpy.array([i in y for i in x])
				b2=numpy.array([i in x for i in y])
				return b-b2
			case "<":
				return numpy.array([i in y for i in x])
			case ">":
				return numpy.array([i in x for i in y])
			case "=":
				x=y
	def interpretpgm(self, astring, i=0):
		val=[]
		hold=0
		if(i=0):
			self.parse(astring)
			self.values=[]
		for j in objs[ix]:
			if(j=="*"):
				val.append(self.values.pop())
			else if(j=="v"):
				val.append(self.vtable[int(j.next())])
			else if(j in ["\\",".","#","%"]):
				opstr=j
				val.append(self.op(val.pop(),j))
			if(hold==1):
				val.append(self.op2(val.pop(),val.pop(),j)
				hold=0
			else if(j in [">","<","-", '=']):
				opstr=j
				hold=1
		
		if(i<len(objs)):
			self.values=interpretpgm(astring,vtable,i+1)
		return val
	def __getitem__(self,key):
		return self.vtable[key]
	def __setitem__(self,key,item):
		self.vtable[key]=item
	def __call__(self):
		self.evolve()
		self.sub_evolve()
	def __len__(self):
		return self.res_x
	def __delitem__(self,key):
		del self.vtable[key]
	def __mod__(self,x):
		return self.interpretpgm(x)
	def __iadd__(self,x):
		self.append_child(x, x.estring)	
	def __radd__(self,x):
		self.attach_to_parent(x)
	def __imod__(self,x)
		self.change_string(x)
			
		
				
					
					
					
			
	
			
			

